#include "demo2d.h"
#include "engine/utils/file_utils.h"
#include "engine/renderer/render_system2d.h"
#include "engine/core/event_handler.h"


bool HandleEvent(kanon::EventType type, void* sender, void* listener, kanon::EventContext context)
{
    // sample event handling
    if (type == kanon::EventType::EVENT_MOUSE_MOVE)
    {
        float xpos = context.data.f32[0];
        float ypos = context.data.f32[1];
    }
    else if (type == kanon::EventType::EVENT_MOUSE_LEFT_DOWN)
    {
        // construct a particle
        float xpos = context.data.f32[0];  // left->right
        float ypos = context.data.f32[1];  // top->bottom
        Demo2d* app = reinterpret_cast<Demo2d*>(listener);
        uint32_t windowHeight = app->window->GetHeight();
        ypos = windowHeight - ypos;
        glm::vec2 pos = app->camera->ScreenToWorld(xpos, ypos);
#if 0
        app->actor_system->CreateParticleSystem(pos, glm::vec4(0.7f, 0.7f, 0.3f, 1.0f), 300);
#else
        int32_t index = app->actor_system->Pick(pos);
        std::cout << index << std::endl;
        app->selected_actor_index = index;
#endif
    }
    else if (type == kanon::EventType::EVENT_KEY_PRESS || type == kanon::EventType::EVENT_KEY_REPEAT)
    {
        // get keycode
        uint8_t key = context.data.u8[0];
        Demo2d* app = reinterpret_cast<Demo2d*>(listener);
        if (key == GLFW_KEY_W) app->camera->Move(0, 0.01f);
        else if (key == GLFW_KEY_A) app->camera->Move(-0.01f, 0);
        else if (key == GLFW_KEY_S) app->camera->Move(0, -0.01f);
        else if (key == GLFW_KEY_D) app->camera->Move(0.01f, 0);
        else if (key == GLFW_KEY_Q) app->camera->Rotate(0.01f);
        else if (key == GLFW_KEY_E) app->camera->Rotate(-0.01f);
    }
    return true;
}

Demo2d::Demo2d()
    :BaseApp()
{

}

void Demo2d::Initialize()
{
    BaseApp::Initialize();

    uint32_t width = window->GetWidth();
    uint32_t height = window->GetHeight();
    render_system2d = std::make_shared<kanon::RenderSystem2d>(width, height);

    // colored sprite
    actor_system->CreateSprite(glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec4(1.0f, 1.0f, 1.0f, 1.0f));
    std::string texture_path = kanon::FileUtils::getTexturePath("mars.jpg");
    std::shared_ptr<kanon::Texture2D> texture = kanon::get_texture(texture_path);
    actor_system->CreateSprite(glm::vec2(0.0f, -0.2f), glm::vec2(0.3f, 0.3f), texture);
    actor_system->CreateCircle(glm::vec2(0.0f, 0.0f), glm::vec2(0.2f, 0.2f), glm::vec4(1.0f, 0.4f, 0.3f, 1.0f));

    // create camera
    camera = std::make_shared<kanon::Camera2d>();
    camera->SetWindowSize(window->GetWidth(), window->GetHeight());
}

void Demo2d::Render()
{
    render_system2d->Begin();
    render_system2d->SetCamera2D(camera);
    render_system2d->Render(actor_system);

    if (selected_actor_index >= 0)
        render_system2d->RenderSelected(actor_system, selected_actor_index);

    render_system2d->End();

    this->RenderUI();
}


void Demo2d::RegisterEvents()
{
    std::vector<kanon::EventType> event_types = {
            kanon::EventType::EVENT_KEY_PRESS,
            kanon::EventType::EVENT_KEY_REPEAT,
            kanon::EventType::EVENT_MOUSE_MOVE,
            kanon::EventType::EVENT_MOUSE_LEFT_DOWN,
    };
    for (auto& evt : event_types)
        register_event(evt, this, HandleEvent);
}

void Demo2d::RenderUI()
{
    ui_layer->BeginFrame();
    ui_layer->BeginWindow("sample");
    
    ui_layer->EndWindow();
    ui_layer->EndFrame();
}
